

<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>dynamic_rest.routers &mdash; Dynamic REST 1.3.15 documentation</title>
  

  
  

  

  
  
    

  

  
  
    <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  

  

  
    <link rel="top" title="Dynamic REST 1.3.15 documentation" href="../../index.html"/>
        <link rel="up" title="Module code" href="../index.html"/> 

  
  <script src="../../_static/js/modernizr.min.js"></script>

</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search">
          

          
            <a href="../../index.html" class="icon icon-home"> Dynamic REST
          

          
          </a>

          
            
            
              <div class="version">
                1.3.15
              </div>
            
          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

          
        </div>

        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          
            
            
                <p class="caption"><span class="caption-text">Contents</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../tutorial.html">Dynamic REST Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dynamic_rest.html">dynamic_rest package</a></li>
</ul>

            
          
        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="../../index.html">Dynamic REST</a>
      </nav>


      
      <div class="wy-nav-content">
        <div class="rst-content">
          





<div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="../../index.html">Docs</a> &raquo;</li>
      
          <li><a href="../index.html">Module code</a> &raquo;</li>
      
    <li>dynamic_rest.routers</li>
      <li class="wy-breadcrumbs-aside">
        
          
        
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <h1>Source code for dynamic_rest.routers</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;This module contains custom router classes.&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">OrderedDict</span>

<span class="kn">from</span> <span class="nn">django.utils</span> <span class="kn">import</span> <span class="n">six</span>
<span class="kn">from</span> <span class="nn">rest_framework</span> <span class="kn">import</span> <span class="n">views</span>
<span class="kn">from</span> <span class="nn">rest_framework.response</span> <span class="kn">import</span> <span class="n">Response</span>
<span class="kn">from</span> <span class="nn">rest_framework.reverse</span> <span class="kn">import</span> <span class="n">reverse</span>
<span class="kn">from</span> <span class="nn">rest_framework.routers</span> <span class="kn">import</span> <span class="n">DefaultRouter</span><span class="p">,</span> <span class="n">Route</span><span class="p">,</span> <span class="n">replace_methodname</span>

<span class="kn">from</span> <span class="nn">dynamic_rest.meta</span> <span class="kn">import</span> <span class="n">get_model_table</span>

<span class="n">directory</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">resource_map</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">resource_name_map</span> <span class="o">=</span> <span class="p">{}</span>


<div class="viewcode-block" id="get_directory"><a class="viewcode-back" href="../../dynamic_rest.html#dynamic_rest.routers.get_directory">[docs]</a><span class="k">def</span> <span class="nf">get_directory</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Get API directory as a nested list of lists.&quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">get_url</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">request</span><span class="o">=</span><span class="n">request</span><span class="p">)</span> <span class="k">if</span> <span class="n">url</span> <span class="k">else</span> <span class="n">url</span>

    <span class="k">def</span> <span class="nf">is_active_url</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="k">if</span> <span class="n">url</span> <span class="ow">and</span> <span class="n">path</span> <span class="k">else</span> <span class="bp">False</span>

    <span class="n">path</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">path</span>
    <span class="n">directory_list</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">sort_key</span><span class="p">(</span><span class="n">r</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">r</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

    <span class="c1"># TODO(ant): support arbitrarily nested</span>
    <span class="c1"># structure, for now it is capped at a single level</span>
    <span class="c1"># for UX reasons</span>
    <span class="k">for</span> <span class="n">group_name</span><span class="p">,</span> <span class="n">endpoints</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span>
        <span class="n">six</span><span class="o">.</span><span class="n">iteritems</span><span class="p">(</span><span class="n">directory</span><span class="p">),</span>
        <span class="n">key</span><span class="o">=</span><span class="n">sort_key</span>
    <span class="p">):</span>
        <span class="n">endpoints_list</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">endpoint_name</span><span class="p">,</span> <span class="n">endpoint</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span>
            <span class="n">six</span><span class="o">.</span><span class="n">iteritems</span><span class="p">(</span><span class="n">endpoints</span><span class="p">),</span>
            <span class="n">key</span><span class="o">=</span><span class="n">sort_key</span>
        <span class="p">):</span>
            <span class="k">if</span> <span class="n">endpoint_name</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;_&#39;</span><span class="p">:</span>
                <span class="k">continue</span>
            <span class="n">endpoint_url</span> <span class="o">=</span> <span class="n">get_url</span><span class="p">(</span><span class="n">endpoint</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;_url&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">))</span>
            <span class="n">active</span> <span class="o">=</span> <span class="n">is_active_url</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">endpoint_url</span><span class="p">)</span>
            <span class="n">endpoints_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
                <span class="p">(</span><span class="n">endpoint_name</span><span class="p">,</span> <span class="n">endpoint_url</span><span class="p">,</span> <span class="p">[],</span> <span class="n">active</span><span class="p">)</span>
            <span class="p">)</span>

        <span class="n">url</span> <span class="o">=</span> <span class="n">get_url</span><span class="p">(</span><span class="n">endpoints</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;_url&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">))</span>
        <span class="n">active</span> <span class="o">=</span> <span class="n">is_active_url</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">url</span><span class="p">)</span>
        <span class="n">directory_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
            <span class="p">(</span><span class="n">group_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">endpoints_list</span><span class="p">,</span> <span class="n">active</span><span class="p">)</span>
        <span class="p">)</span>
    <span class="k">return</span> <span class="n">directory_list</span></div>


<div class="viewcode-block" id="DynamicRouter"><a class="viewcode-back" href="../../dynamic_rest.html#dynamic_rest.routers.DynamicRouter">[docs]</a><span class="k">class</span> <span class="nc">DynamicRouter</span><span class="p">(</span><span class="n">DefaultRouter</span><span class="p">):</span></div>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="n">optional_trailing_slash</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;optional_trailing_slash&#39;</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">DynamicRouter</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">optional_trailing_slash</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">trailing_slash</span> <span class="o">=</span> <span class="s1">&#39;/?&#39;</span>

    <span class="k">def</span> <span class="nf">get_api_root_view</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Return API root view, using the global directory.&quot;&quot;&quot;</span>
        <span class="k">class</span> <span class="nc">API</span><span class="p">(</span><span class="n">views</span><span class="o">.</span><span class="n">APIView</span><span class="p">):</span>
            <span class="n">_ignore_model_permissions</span> <span class="o">=</span> <span class="bp">True</span>

            <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
                <span class="n">directory_list</span> <span class="o">=</span> <span class="n">get_directory</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
                <span class="n">result</span> <span class="o">=</span> <span class="n">OrderedDict</span><span class="p">()</span>
                <span class="k">for</span> <span class="n">group_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">endpoints</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">directory_list</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">url</span><span class="p">:</span>
                        <span class="n">result</span><span class="p">[</span><span class="n">group_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">url</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">group</span> <span class="o">=</span> <span class="n">OrderedDict</span><span class="p">()</span>
                        <span class="k">for</span> <span class="n">endpoint_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">endpoints</span><span class="p">:</span>
                            <span class="n">group</span><span class="p">[</span><span class="n">endpoint_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">url</span>
                        <span class="n">result</span><span class="p">[</span><span class="n">group_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">group</span>
                <span class="k">return</span> <span class="n">Response</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">API</span><span class="o">.</span><span class="n">as_view</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">register</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prefix</span><span class="p">,</span> <span class="n">viewset</span><span class="p">,</span> <span class="n">base_name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Add any registered route into a global API directory.</span>

<span class="sd">        If the prefix includes a path separator,</span>
<span class="sd">        store the URL in the directory under the first path segment.</span>
<span class="sd">        Otherwise, store it as-is.</span>

<span class="sd">        For example, if there are two registered prefixes,</span>
<span class="sd">        &#39;v1/users&#39; and &#39;groups&#39;, `directory` will look liks:</span>

<span class="sd">        {</span>
<span class="sd">            &#39;v1&#39;: {</span>
<span class="sd">                &#39;users&#39;: {</span>
<span class="sd">                    &#39;_url&#39;: &#39;users-list&#39;</span>
<span class="sd">                    &#39;_viewset&#39;: &lt;class &#39;UserViewSet&#39;&gt;</span>
<span class="sd">                },</span>
<span class="sd">            }</span>
<span class="sd">            &#39;groups&#39;: {</span>
<span class="sd">               &#39;_url&#39;: &#39;groups-list&#39;</span>
<span class="sd">               &#39;_viewset&#39;: &lt;class &#39;GroupViewSet&#39;&gt;</span>
<span class="sd">            }</span>
<span class="sd">        }</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">base_name</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">base_name</span> <span class="o">=</span> <span class="n">prefix</span>

        <span class="nb">super</span><span class="p">(</span><span class="n">DynamicRouter</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">prefix</span><span class="p">,</span> <span class="n">viewset</span><span class="p">,</span> <span class="n">base_name</span><span class="p">)</span>

        <span class="n">prefix_parts</span> <span class="o">=</span> <span class="n">prefix</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">prefix_parts</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">prefix</span> <span class="o">=</span> <span class="n">prefix_parts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
            <span class="n">endpoint</span> <span class="o">=</span> <span class="s1">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">prefix_parts</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">endpoint</span> <span class="o">=</span> <span class="n">prefix</span>
            <span class="n">prefix</span> <span class="o">=</span> <span class="bp">None</span>

        <span class="k">if</span> <span class="n">prefix</span> <span class="ow">and</span> <span class="n">prefix</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">directory</span><span class="p">:</span>
            <span class="n">current</span> <span class="o">=</span> <span class="n">directory</span><span class="p">[</span><span class="n">prefix</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">current</span> <span class="o">=</span> <span class="n">directory</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">prefix</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span>

        <span class="n">list_name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">routes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">name</span>
        <span class="n">url_name</span> <span class="o">=</span> <span class="n">list_name</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">basename</span><span class="o">=</span><span class="n">base_name</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">endpoint</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current</span><span class="p">:</span>
            <span class="n">current</span><span class="p">[</span><span class="n">endpoint</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="n">current</span><span class="p">[</span><span class="n">endpoint</span><span class="p">][</span><span class="s1">&#39;_url&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">url_name</span>
        <span class="n">current</span><span class="p">[</span><span class="n">endpoint</span><span class="p">][</span><span class="s1">&#39;_viewset&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">viewset</span>

    <span class="k">def</span> <span class="nf">register_resource</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">viewset</span><span class="p">,</span> <span class="n">namespace</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Register a viewset that should be considered the canonical</span>
<span class="sd">        endpoint for a particular resource. In addition to generating</span>
<span class="sd">        and registering the route, it adds the route in a reverse map</span>
<span class="sd">        to allow DREST to build the canonical URL for a given resource.</span>

<span class="sd">        Arguments:</span>
<span class="sd">            viewset - viewset class, should have `serializer_class` attr.</span>
<span class="sd">            namespace - (optional) URL namespace, e.g. &#39;v3&#39;.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># Try to extract resource name from viewset.</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">serializer</span> <span class="o">=</span> <span class="n">viewset</span><span class="o">.</span><span class="n">serializer_class</span><span class="p">()</span>
            <span class="n">resource_key</span> <span class="o">=</span> <span class="n">serializer</span><span class="o">.</span><span class="n">get_resource_key</span><span class="p">()</span>
            <span class="n">resource_name</span> <span class="o">=</span> <span class="n">serializer</span><span class="o">.</span><span class="n">get_name</span><span class="p">()</span>
            <span class="n">path_name</span> <span class="o">=</span> <span class="n">serializer</span><span class="o">.</span><span class="n">get_plural_name</span><span class="p">()</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="kn">import</span> <span class="nn">traceback</span>
            <span class="n">traceback</span><span class="o">.</span><span class="n">print_exc</span><span class="p">()</span>
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
                <span class="s2">&quot;Failed to extract resource name from viewset: &#39;</span><span class="si">%s</span><span class="s2">&#39;.&quot;</span>
                <span class="s2">&quot; It, or its serializer, may not be DREST-compatible.&quot;</span> <span class="o">%</span> <span class="p">(</span>
                    <span class="n">viewset</span>
                <span class="p">)</span>
            <span class="p">)</span>

        <span class="c1"># Construct canonical path and register it.</span>
        <span class="k">if</span> <span class="n">namespace</span><span class="p">:</span>
            <span class="n">namespace</span> <span class="o">=</span> <span class="n">namespace</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;/&#39;</span>
        <span class="n">base_path</span> <span class="o">=</span> <span class="n">namespace</span> <span class="ow">or</span> <span class="s1">&#39;&#39;</span>
        <span class="n">base_path</span> <span class="o">=</span> <span class="s1">r&#39;</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">base_path</span> <span class="o">+</span> <span class="n">path_name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">base_path</span><span class="p">,</span> <span class="n">viewset</span><span class="p">)</span>

        <span class="c1"># Make sure resource isn&#39;t already registered.</span>
        <span class="k">if</span> <span class="n">resource_key</span> <span class="ow">in</span> <span class="n">resource_map</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
                <span class="s2">&quot;The resource &#39;</span><span class="si">%s</span><span class="s2">&#39; has already been mapped to &#39;</span><span class="si">%s</span><span class="s2">&#39;.&quot;</span>
                <span class="s2">&quot; Each resource can only be mapped to one canonical&quot;</span>
                <span class="s2">&quot; path. &quot;</span> <span class="o">%</span> <span class="p">(</span>
                    <span class="n">resource_key</span><span class="p">,</span>
                    <span class="n">resource_map</span><span class="p">[</span><span class="n">resource_key</span><span class="p">][</span><span class="s1">&#39;path&#39;</span><span class="p">]</span>
                <span class="p">)</span>
            <span class="p">)</span>

        <span class="c1"># Register resource in reverse map.</span>
        <span class="n">resource_map</span><span class="p">[</span><span class="n">resource_key</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s1">&#39;path&#39;</span><span class="p">:</span> <span class="n">base_path</span><span class="p">,</span>
            <span class="s1">&#39;viewset&#39;</span><span class="p">:</span> <span class="n">viewset</span>
        <span class="p">}</span>

        <span class="c1"># Make sure the resource name isn&#39;t registered, either</span>
        <span class="c1"># TODO: Think of a better way to clean this up, there&#39;s a lot of</span>
        <span class="c1"># duplicated effort here, between `resource_name` and `resource_key`</span>
        <span class="c1"># This resource name -&gt; key mapping is currently only used by</span>
        <span class="c1"># the DynamicGenericRelationField</span>
        <span class="k">if</span> <span class="n">resource_name</span> <span class="ow">in</span> <span class="n">resource_name_map</span><span class="p">:</span>
            <span class="n">resource_key</span> <span class="o">=</span> <span class="n">resource_name_map</span><span class="p">[</span><span class="n">resource_name</span><span class="p">]</span>
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
                <span class="s2">&quot;The resource name &#39;</span><span class="si">%s</span><span class="s2">&#39; has already been mapped to &#39;</span><span class="si">%s</span><span class="s2">&#39;.&quot;</span>
                <span class="s2">&quot; A resource name can only be used once.&quot;</span> <span class="o">%</span> <span class="p">(</span>
                    <span class="n">resource_name</span><span class="p">,</span>
                    <span class="n">resource_map</span><span class="p">[</span><span class="n">resource_key</span><span class="p">][</span><span class="s1">&#39;path&#39;</span><span class="p">]</span>
                <span class="p">)</span>
            <span class="p">)</span>

        <span class="c1"># map the resource name to the resource key for easier lookup</span>
        <span class="n">resource_name_map</span><span class="p">[</span><span class="n">resource_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">resource_key</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">get_canonical_path</span><span class="p">(</span><span class="n">resource_key</span><span class="p">,</span> <span class="n">pk</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return canonical resource path.</span>

<span class="sd">        Arguments:</span>
<span class="sd">            resource_key - Canonical resource key</span>
<span class="sd">                           i.e. Serializer.get_resource_key().</span>
<span class="sd">            pk - (Optional) Object&#39;s primary key for a single-resource URL.</span>
<span class="sd">        Returns: Absolute URL as string.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="n">resource_key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">resource_map</span><span class="p">:</span>
            <span class="c1"># Note: Maybe raise?</span>
            <span class="k">return</span> <span class="bp">None</span>

        <span class="n">base_path</span> <span class="o">=</span> <span class="s1">&#39;/&#39;</span> <span class="o">+</span> <span class="n">resource_map</span><span class="p">[</span><span class="n">resource_key</span><span class="p">][</span><span class="s1">&#39;path&#39;</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">pk</span><span class="p">:</span>
            <span class="k">return</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">/</span><span class="si">%s</span><span class="s1">/&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">base_path</span><span class="p">,</span> <span class="n">pk</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">base_path</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">get_canonical_serializer</span><span class="p">(</span>
        <span class="n">resource_key</span><span class="p">,</span>
        <span class="n">model</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
        <span class="n">instance</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
        <span class="n">resource_name</span><span class="o">=</span><span class="bp">None</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return canonical serializer for a given resource name.</span>

<span class="sd">        Arguments:</span>
<span class="sd">            resource_key - Resource key, usually DB table for model-based</span>
<span class="sd">                           resources, otherwise the plural name.</span>
<span class="sd">            model - (Optional) Model class to look up by.</span>
<span class="sd">            instance - (Optional) Model object instance.</span>
<span class="sd">        Returns: serializer class</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="n">model</span><span class="p">:</span>
            <span class="n">resource_key</span> <span class="o">=</span> <span class="n">get_model_table</span><span class="p">(</span><span class="n">model</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">instance</span><span class="p">:</span>
            <span class="n">resource_key</span> <span class="o">=</span> <span class="n">instance</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">db_table</span>
        <span class="k">elif</span> <span class="n">resource_name</span><span class="p">:</span>
            <span class="n">resource_key</span> <span class="o">=</span> <span class="n">resource_name_map</span><span class="p">[</span><span class="n">resource_name</span><span class="p">]</span>

        <span class="k">if</span> <span class="n">resource_key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">resource_map</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">None</span>

        <span class="k">return</span> <span class="n">resource_map</span><span class="p">[</span><span class="n">resource_key</span><span class="p">][</span><span class="s1">&#39;viewset&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">serializer_class</span>

    <span class="k">def</span> <span class="nf">get_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">viewset</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        DREST routes injection, overrides DRF&#39;s get_routes() method, which</span>
<span class="sd">        gets called for each registered viewset.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">routes</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">DynamicRouter</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">get_routes</span><span class="p">(</span><span class="n">viewset</span><span class="p">)</span>
        <span class="n">routes</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_relation_routes</span><span class="p">(</span><span class="n">viewset</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">routes</span>

    <span class="k">def</span> <span class="nf">get_relation_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">viewset</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Generate routes to serve relational objects. This method will add</span>
<span class="sd">        a sub-URL for each relational field.</span>

<span class="sd">        e.g.</span>
<span class="sd">        A viewset for the following serializer:</span>

<span class="sd">          class UserSerializer(..):</span>
<span class="sd">              events = DynamicRelationField(EventSerializer, many=True)</span>
<span class="sd">              groups = DynamicRelationField(GroupSerializer, many=True)</span>
<span class="sd">              location = DynamicRelationField(LocationSerializer)</span>

<span class="sd">        will have the following URLs added:</span>

<span class="sd">          /users/&lt;pk&gt;/events/</span>
<span class="sd">          /users/&lt;pk&gt;/groups/</span>
<span class="sd">          /users/&lt;pk&gt;/location/</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">routes</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">viewset</span><span class="p">,</span> <span class="s1">&#39;serializer_class&#39;</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">routes</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">viewset</span><span class="p">,</span> <span class="s1">&#39;list_related&#39;</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">routes</span>

        <span class="n">serializer</span> <span class="o">=</span> <span class="n">viewset</span><span class="o">.</span><span class="n">serializer_class</span><span class="p">()</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">serializer</span><span class="p">,</span> <span class="s1">&#39;get_link_fields&#39;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="p">[])()</span>

        <span class="n">route_name</span> <span class="o">=</span> <span class="s1">&#39;{basename}-{methodnamehyphen}&#39;</span>

        <span class="k">for</span> <span class="n">field_name</span><span class="p">,</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">six</span><span class="o">.</span><span class="n">iteritems</span><span class="p">(</span><span class="n">fields</span><span class="p">):</span>
            <span class="n">methodname</span> <span class="o">=</span> <span class="s1">&#39;list_related&#39;</span>
            <span class="n">url</span> <span class="o">=</span> <span class="p">(</span>
                <span class="s1">r&#39;^{prefix}/{lookup}/(?P&lt;field_name&gt;</span><span class="si">%s</span><span class="s1">)&#39;</span>
                <span class="s1">&#39;{trailing_slash}$&#39;</span> <span class="o">%</span> <span class="n">field_name</span>
            <span class="p">)</span>
            <span class="n">routes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">Route</span><span class="p">(</span>
                <span class="n">url</span><span class="o">=</span><span class="n">url</span><span class="p">,</span>
                <span class="n">mapping</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;get&#39;</span><span class="p">:</span> <span class="n">methodname</span><span class="p">},</span>
                <span class="n">name</span><span class="o">=</span><span class="n">replace_methodname</span><span class="p">(</span><span class="n">route_name</span><span class="p">,</span> <span class="n">field_name</span><span class="p">),</span>
                <span class="n">initkwargs</span><span class="o">=</span><span class="p">{}</span>
            <span class="p">))</span>
        <span class="k">return</span> <span class="n">routes</span>
</pre></div>

           </div>
          </div>
          <footer>
  

  <hr/>

  <div role="contentinfo">
    <p>
        &copy; Copyright 2016, ant@altschool.com, ryo@altschool.com.

    </p>
  </div>
  Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 

</footer>

        </div>
      </div>

    </section>

  </div>
  


  

    <script type="text/javascript">
        var DOCUMENTATION_OPTIONS = {
            URL_ROOT:'../../',
            VERSION:'1.3.15',
            COLLAPSE_INDEX:false,
            FILE_SUFFIX:'.html',
            HAS_SOURCE:  true
        };
    </script>
      <script type="text/javascript" src="../../_static/jquery.js"></script>
      <script type="text/javascript" src="../../_static/underscore.js"></script>
      <script type="text/javascript" src="../../_static/doctools.js"></script>

  

  
  
    <script type="text/javascript" src="../../_static/js/theme.js"></script>
  

  
  
  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.StickyNav.enable();
      });
  </script>
   

</body>
</html>